#pragma once

#include "cv.h"
//#include "sobel.h"
#include "OpticalFlow.h"
#include "aviprocessor.h"
#include "process.h"
//#include "cvisionDlg.h"

#include <vector>  

// typedef struct _tagthreadarglist
// {
// 	void *g;
// 	int *pfreamno;
// 	float *penergy;
// 	float *penergydiff;
// 	float *pmutualinfo;
// 	float *pnmutualinfo;
// }Threadarglist;

class OpticalflowVideoController 
{

private:

	static OpticalflowVideoController *singleton; // pointer to the singleton

	AviProcessor *aviproc;
	//Sobel *sobel;
	OpticalFlow *opticalflow;

	//Threadarglist *threadarglist;


	OpticalflowVideoController() 
	{ // private constructor

		//setting up the application
		aviproc= new AviProcessor();
		//sobel= new Sobel();
		opticalflow = new OpticalFlow();
		aviproc->setImageProcess(process);
		aviproc->callProcess();
		aviproc->setDisplay(true);
	}

public:

	void run(int *pframeno, float *penergy, float *penergydiff, float *pmutualinfo, float *pnmutualinfo) 
	{
// 		threadarglist->g = reinterpret_cast<LPVOID>(this);
// 		threadarglist->pfreamno = pframeno;
// 		threadarglist->penergy = penergy;
// 		threadarglist->penergydiff = penergydiff;
// 		threadarglist->pmutualinfo = pmutualinfo;
// 		threadarglist->pnmutualinfo = pnmutualinfo;
		aviproc->energy = penergy;
		aviproc->energydiff = penergydiff;
		aviproc->mutualinfo = pmutualinfo;
		aviproc->nmutualinfo = pnmutualinfo;
		aviproc->frameno = pframeno;

		aviproc->run(/*threadarglist*/);
	}

	void stop() 
	{

		aviproc->stopIt();
	}

	void pause(int duration)
	{
		aviproc->setDelay(duration);
	}

	// to be called by the callback
	inline void processImage(IplImage *image, float* penergy, float* penergydiff, float* pmutualinfo, float* pnmutualinfo) 
	{

		opticalflow->processImage(image, aviproc->getFrameNumber(),  penergy,  penergydiff,  pmutualinfo,  pnmutualinfo);

	}

	inline void setFile(CString filename) 
	{

		aviproc->setFile(filename);
	}

	inline IplImage* getOutputImage() 
	{

		//return sobel->getOutputImage();
		return opticalflow->getOutputImage();
	}

	inline int getFramenumber()
	{
		return aviproc->getFrameNumber();
	}
	
	inline float getEnergy()
	{
		return opticalflow->getEnergy();
	}

	inline float getEnergyDiff()
	{
		return opticalflow->getEnergyDiff();
	}

	inline float getMutualInfo()
	{
		return opticalflow->getMutualInfo();
	}

	inline float getNMutualInfo()
	{
		return opticalflow->getNMutualInfo();
	}

	~OpticalflowVideoController() 
	{

		delete aviproc;
		//delete sobel;
		delete opticalflow;
	}

	// Singleton static members
	static OpticalflowVideoController *getInstance()
	{

		if (singleton == 0)
			singleton= new OpticalflowVideoController;

		return singleton;
	}

	static void destroy()
	{

		if (singleton != 0) 
		{
			delete singleton;
			singleton= 0;
		}
	}
};